--[[ Utility Functions ]]


---------------------------------------------------------------------------
-- Broadcast messages to screen
---------------------------------------------------------------------------
function BroadcastMessage( sMessage, fDuration,iPlayer )
	local centerMessage = {
		message = sMessage,
		duration = fDuration
	}
	if iPlayer then
		centerMessage["player_id"] = iPlayer
	end
	FireGameEvent( "show_center_message", centerMessage )
end
--[[
	获取npc的位置，前期用path_corner，后期直接批量替换成位置坐标
]]
function getEntityByName( npcName )
	--暂时直接查找  todo change
	return Entities:FindByName(nil,npcName)
end

function doTeleport( caster,point_name )
	FindClearSpaceForUnit(caster,getEntityPosition(point_name) , true)
	local id = caster:GetPlayerOwnerID()
	caster:Stop()
	PlayerResource:SetCameraTarget(id, caster)
	local selfGameMode = GameRules:GetGameModeEntity()
	selfGameMode:SetContextThink(DoUniqueString("cameraMove"),
	function (  ) PlayerResource:SetCameraTarget(id, nil) end,0.5)
end

function getItemInWeightlist( list,num,total )
	num = num or 1
	local ret = {}
	for i=1,num do
		local rd = RandomFloat(1,total)
		for k,v in pairs(list) do
			if v.from <= rd and v.to >= rd then
				table.insert(ret,k)
				break
			end
		end
	end
	return ret
end
--[[
	检测是否拥有某个物品
]]
function checkHasItem( hero,itemName,itemCount )
	itemCount = itemCount or 1
	for i=0,5 do
		local item = hero:GetItemInSlot(i)
		if item and item:GetAbilityName() == itemName then
			if item:IsStackable() then
				itemCount = itemCount - item:GetCurrentCharges()
			else
				itemCount = itemCount - 1
			end
		end
	end
	local playerId = hero:GetPlayerOwnerID()
	if itemCount < 1 or roleData:checkHasItem(playerId,itemName,itemCount) then
		return true
	end
	return false
end
--[[
	这个函数的前提是玩家拥有该物品
]]
function removeItemByName( hero,itemName,itemCount )
	itemCount = itemCount or 1
	for i=0,5 do
		local item = hero:GetItemInSlot(i)
		if item and item:GetAbilityName() == itemName then
			if item:IsStackable() then
				local cur = item:GetCurrentCharges()
				itemCount = itemCount - cur
				if itemCount > 0 then
					hero:RemoveItem(item)
				else
					item:SetCurrentCharges(-itemCount)
					return true
				end
			else
				itemCount = itemCount - 1
				hero:RemoveItem(item)
				if itemCount <= 0 then
					return true
				end
			end
		end
	end
	local playerId = hero:GetPlayerOwnerID()
	roleData.removeItemByName(playerId,itemName,itemCount)
end

--[[
	
]]
function createTimerBar( total,func,str,args,checkResume )
	local cur = 0

	local index = DoUniqueString("timerBar")
	local ret = Timers:CreateTimer(function (  )
		if cur >= total then
			if func then
				func()
			end
			--移除ui
			CustomGameEventManager:Send_ServerToAllClients("S2C_REMOVE_TIME",{index=index})
			return nil
		else
			if not checkResume or checkResume() then
				CustomGameEventManager:Send_ServerToAllClients("S2C_CHANGE_TIME",{cur=cur,total=total,str=str,args = args,index=index})
				cur = cur + 1
			end
			return 1
		end
	end)
	return ret
end

function SellItemCustom( playerId,item )
	local gold = GetItemCost(item:GetAbilityName())
	item:RemoveSelf()
	gold = math.floor(gold * SELL_PERCENT)
	roleData.modify_gold(playerId,gold)
end

function enhanceState( item,playerId )
	local hPlayer = PlayerResource:GetPlayer(playerId)
	CustomGameEventManager:Send_ServerToPlayer(hPlayer,"S2C_GOTO_ENHANCE",{})
end

function showWarn(message,player_id)
	local hPlayer
	local _t = type(player_id)
	if _t == 'number' then
		hPlayer = PlayerResource:GetPlayer(player_id)
	else
		hPlayer = player_id:GetPlayerOwner()
	end
	CustomGameEventManager:Send_ServerToPlayer(hPlayer,"S2C_ERROR_MSG",{text = message})
end
--判断是否物品栏满了
function isFullInvent(hero)
	for i=0,5 do
		local item = hero:GetItemInSlot(i)
		if not item then
			return false
		end
	end
	return true
end

function addItemToBackPack(hero,itemIndex)
	local playerId = hero:GetPlayerOwnerID()
	return roleData.addItemToBackPack(playerId,itemIndex)
end

function addItemToPlayer(hero,itemName,itemCount)
	itemCount = itemCount or 1
	for i=1,itemCount do
		local newitem = CreateItem(itemName,nil,nil)
		newitem:SetPurchaseTime(0)
		local bfind = false
		for i=0,5 do
			local item = hero:GetItemInSlot(i)
			if not item then
				hero:AddItem(newitem)
				bfind = true
				break
			end
		end
		print(bfind)
		if not bfind then
			--物品栏已满 放入背包
			local playerId = hero:GetPlayerOwnerID()
			if roleData.addItemToBackPack(playerId,newitem:entindex()) then
				hero:TakeItem(newitem)
			else
				local drop = CreateItemOnPositionSync( hero:GetOrigin() + RandomVector( RandomFloat(50, 100)) , newitem)
				if drop then
					drop:SetContainedItem( newitem )
				end
			end
		end
	end
end
--由前端判断是否与背包有关
function moveItem(hero,itemIndex,itemIndex2)

end

function Dujie( hero )
	
end

local function dump_value_(v)
    if type(v) == "string" then
        v = "\"" .. v .. "\""
    end
    return tostring(v)
end
function dump(value, desciption, nesting)
    if type(nesting) ~= "number" then nesting = 3 end

    local lookupTable = {}
    local result = {}

    local function dump_(value, desciption, indent, nest, keylen)
        desciption = desciption or "<var>"
        local spc = ""
        if type(keylen) == "number" then
            spc = string.rep(" ", keylen - string.len(dump_value_(desciption)))
        end
        if type(value) ~= "table" then
            result[#result +1 ] = string.format("%s%s%s = %s", indent, dump_value_(desciption), spc, dump_value_(value))
        elseif lookupTable[tostring(value)] then
            result[#result +1 ] = string.format("%s%s%s = *REF*", indent, dump_value_(desciption), spc)
        else
            lookupTable[tostring(value)] = true
            if nest > nesting then
                result[#result +1 ] = string.format("%s%s = *MAX NESTING*", indent, dump_value_(desciption))
            else
                result[#result +1 ] = string.format("%s%s = {", indent, dump_value_(desciption))
                local indent2 = indent.."    "
                local keys = {}
                local keylen = 0
                local values = {}
                for k, v in pairs(value) do
                    keys[#keys + 1] = k
                    local vk = dump_value_(k)
                    local vkl = string.len(vk)
                    if vkl > keylen then keylen = vkl end
                    values[k] = v
                end
                table.sort(keys, function(a, b)
                    if type(a) == "number" and type(b) == "number" then
                        return a < b
                    else
                        return tostring(a) < tostring(b)
                    end
                end)
                for i, k in ipairs(keys) do
                    dump_(values[k], k, indent2, nest + 1, keylen)
                end
                result[#result +1] = string.format("%s}", indent)
            end
        end
    end
    dump_(value, desciption, "- ", 1)

    for i, line in ipairs(result) do
        print(line)
    end
end

function getUnitZZ( name )
	local fmt = "([%a]*)[_%d]-"
	return name:match(fmt)
end

--克隆一个物品
function cloneItem(item)
	local itemName = item:GetAbilityName()
	local newItem = CreateItem(itemName, nil, nil)
	for k,v in pairs(item.attrs) do
		newItem.attrs[k] = v
	end
end
function CreateItemFrxxz( itemName )
	local item = CreateItem(itemName,nil,nil)
	item:SetPurchaseTime(0)
	local attrs = roleData.getAttrEnums()
	item.attrs = {} --基础属性
	for i,v in ipairs(attrs) do
		local val = item:GetSpecialValueFor("attr_"..v)
		if val and val > 0 then
			item.attrs[v] = val
		end
	end
	item.eattr = {} --这个是强化得到的随机属性

end

function calcCustomProperty( caster )

	-- --下面是自定义属性，每秒进行一次  比写在damagefilter中应该要更平均一点
	-- --这里分别获取基础属性和强化属性
	-- local basic_attrs = item.attrs or {}  --基础属性
	-- local forge_attrs = item.eattr or {}  --强化属性
	-- local total_attrs = {}
	-- for k,v in pairs(basic_attrs) do
	-- 	if not total_attrs[k] then
	-- 		total_attrs[k] = v
	-- 	else
	-- 		total_attrs[k] = total_attrs[k] + v
	-- 	end
	-- end
	-- for k,v in pairs(forge_attrs) do
	-- 	if not total_attrs[k] then
	-- 		total_attrs[k] = v
	-- 	else
	-- 		total_attrs[k] = total_attrs[k] + v
	-- 	end
	-- end
	-- caster.equip_attr = total_attrs
	if not caster:IsRealHero() then
		return
	end
	local _attrs = {}
	for i,v in ipairs(EQUIP_ATTRS) do
		_attrs[v] = 0
	end
	for i=0,5 do
		local item = caster:GetItemInSlot(i)
		if item then
			for _,v in ipairs(EQUIP_ATTRS) do
				local val = item:GetSpecialValueFor(v)
				if val and val ~= 0 then
					if v=="attr_crit_chance" or v=="attr_miss" or v=="attr_mk" then
						--非线性叠加计算
						_attrs[v] = (100-_attrs[v])*val/100+_attrs[v]
					else
						_attrs[v] = _attrs[v] + val
					end
				end
			end

			local eattr = item.eattrs or {}
			for k,v in pairs(eattr) do
				_attrs[k] = _attrs[k] + v
			end
		end
	end
	--基础属性计算
	local primaryState = caster:GetPrimaryAttribute()+2
	_attrs[EQUIP_ATTRS[primaryState]] = _attrs[EQUIP_ATTRS[primaryState]] + _attrs["attr_jcsx"]
	_attrs["attr_jcsx"] = nil
	caster.attrs = _attrs
	local hModifier = caster:FindModifierByName("modifier_custom_property")
	hModifier:ForceRefresh()
	-- local playerId = caster:GetPlayerOwnerID()
	-- roleData.sendAllAttrs(playerId)

	-- caster:RemoveModifierByName("modifier_custom_property")
	-- caster:AddNewModifier(caster, nil, "modifier_custom_property",{})
end

function calcSuitProperty( caster,collectedSuits )
	for i,suitName in ipairs(collectedSuits) do
		--local suitData = 
	end
end
function AddItemOnGround(item_name,unit)
	local item = CreateItem(item_name, nil, nil)
    item:SetPurchaseTime(0)
    local pos = unit:GetAbsOrigin()
    local drop = CreateItemOnPositionSync( pos, item )
    local pos_launch = pos+RandomVector(RandomFloat(150,200))
    item:LaunchLoot(false, 200, 0.75, pos_launch)
end
--[[
	暂时的锻造策略：
	curLevel * (0.008~0.03) + 0.03
]]
function StrengthItem(item,unit)
	local playerId = unit:GetPlayerOwnerID()
	if not item.level then
		item.level = 0
	end
	if not item.eattrs then
		item.eattrs = {}
	end
	if item.level < MAX_STRENGTH_LEVEL then
		local st = math.max(math.floor((item.level-1)/3),0) + 1
		local stoneName = "item_stone"..st
		if checkHasItem(unit,stoneName,1) then
			removeItemByName(unit,stoneName,1)
			if RollPercentage(strengthprob[item.level+1]) then
				for k,v in pairs(EQUIP_ATTRS) do
					local val = item:GetSpecialValueFor(v)
					if val and val ~= 0 then
						local rd = RandomFloat(0.008,0.03)
						if not item.eattrs[v] then
							item.eattrs[v] = 0
						end
						item.eattrs[v] = math.floor(item.eattrs[v] + val * (rd * item.level + 0.03))
					end
				end
				item.level = item.level + 1
				EmitGlobalSound("Tutorial.Notice.Speech")
				calcCustomProperty(unit)
				local gameEvent = {}
				gameEvent["locstring_value"] = "#SUCCEED"
				gameEvent["player_id"] = playerId
				gameEvent["message"] = "#StrengthItem"
				FireGameEvent( "dota_combat_event_message", gameEvent )
			else
				local gameEvent = {}
				gameEvent["locstring_value"] = "#FAILED"
				gameEvent["player_id"] = playerId
				gameEvent["message"] = "#StrengthItem"
				FireGameEvent( "dota_combat_event_message", gameEvent )
				--showWarn("#TIP_STRENGTHEN_FAILED",playerId)
			end
		else
			showWarn("#TIP_HAS_NO_STONE",playerId)
		end
	else
		showWarn("#TIP_ITEM_MAX_LEVEL",playerId)
	end
end

function CreateNewItem(itemName,opr,posorhero)
	local item = CreateItem(itemName,nil,nil)
	if opr == 0 then
		posorhero:AddItem(item)
	else
		local drop = CreateItemOnPositionSync( posorhero, item )
	    local pos_launch = pos+RandomVector(RandomFloat(150,200))
	    item:LaunchLoot(false, 200, 0.75, pos_launch)
	end
	local attrs = roleData.getAttrEnums()
	item.attrs = {}
	for i,v in ipairs(attrs) do
		local val = item:GetSpecialValueFor(v)
		if val > 0 then
			item.attrs[v] = val
		end
	end
	if string.find(itemName,"item_suit") then
		item.level = 1
	end
end
---------------------------------------------------------------------------
-- GetRandomElement
---------------------------------------------------------------------------
function GetRandomElement( table )
	local nRandomIndex = RandomInt( 1, #table )
    local randomElement = table[ nRandomIndex ]
    return randomElement
end

---------------------------------------------------------------------------
-- ShuffledList
---------------------------------------------------------------------------
function ShuffledList( orig_list )
	local list = shallowcopy( orig_list )
	local result = {}
	local count = #list
	for i = 1, count do
		local pick = RandomInt( 1, #list )
		result[ #result + 1 ] = list[ pick ]
		table.remove( list, pick )
	end
	return result
end

---------------------------------------------------------------------------
-- string.starts
---------------------------------------------------------------------------
function string.starts( string, start )
   return string.sub( string, 1, string.len( start ) ) == start
end

---------------------------------------------------------------------------
-- string.split
---------------------------------------------------------------------------
function string.split( str, sep )
    local sep, fields = sep or ":", {}
    local pattern = string.format("([^%s]+)", sep)
    str:gsub(pattern, function(c) fields[#fields+1] = c end)
    return fields
end

---------------------------------------------------------------------------
-- shallowcopy
---------------------------------------------------------------------------
function shallowcopy(orig)
    local orig_type = type(orig)
    local copy
    if orig_type == 'table' then
        copy = {}
        for orig_key, orig_value in pairs(orig) do
            copy[orig_key] = orig_value
        end
    else -- number, string, boolean, etc
        copy = orig
    end
    return copy
end

---------------------------------------------------------------------------
-- Table functions
---------------------------------------------------------------------------
function PrintTable( t, indent )
	--print( "PrintTable( t, indent ): " )
	if type(t) ~= "table" then return end

	for k,v in pairs( t ) do
		if type( v ) == "table" then
			if ( v ~= t ) then
				print( indent .. tostring( k ) .. ":\n" .. indent .. "{" )
				PrintTable( v, indent .. "  " )
				print( indent .. "}" )
			end
		else
		print( indent .. tostring( k ) .. ":" .. tostring(v) )
		end
	end
end

function TableFindKey( table, val )
	if table == nil then
		print( "nil" )
		return nil
	end

	for k, v in pairs( table ) do
		if v == val then
			return k
		end
	end
	return nil
end

function TableLength( t )
	local nCount = 0
	for _ in pairs( t ) do
		nCount = nCount + 1
	end
	return nCount
end

function tablefirstkey( t )
	for k, _ in pairs( t ) do
		return k
	end
	return nil
end

function tablehaselements( t )
	return tablefirstkey( t ) ~= nil
end

function ConvertToTime( value )
  	local value = tonumber( value )

	if value <= 0 then
		return "00:00:00";
	else
	    hours = string.format( "%02.f", math.floor( value / 3600 ) );
	    mins = string.format( "%02.f", math.floor( value / 60 - ( hours * 60 ) ) );
	    secs = string.format( "%02.f", math.floor( value - hours * 3600 - mins * 60 ) );
	    if math.floor( value / 3600 ) == 0 then
	    	return mins .. ":" .. secs
	    end
	    return hours .. ":" .. mins .. ":" .. secs
	end
end

function deepclone( object )
    local lookup_table = {}
    local function _copy(object)
        if type(object) ~= "table" then
            return object
        elseif lookup_table[object] then
            return lookup_table[object]
        end
        local new_table = {}
        lookup_table[object] = new_table
        for key, value in pairs(object) do
            new_table[_copy(key)] = _copy(value)
        end
        return setmetatable(new_table, getmetatable(object))
    end
    return _copy(object)
end

function DebugPrint( ... )
	if IsInToolsMode() then
		print("DebugPrint -- ",...)
	end
end
function ModifyFood( id,food )
	GameRules.food[id+1] = GameRules.food[id+1] +food
	CustomNetTables:SetTableValue("food", tostring(id), {val=GameRules.food[id+1]})
end
function ModifyWood( id,wood )
	GameRules.wood[id+1] = GameRules.wood[id+1] +wood
	CustomNetTables:SetTableValue("wood", tostring(id),{val=GameRules.wood[id+1]})
end

function calcNextPoint( pos,ppos )
	for i=1,#ppos-1 do
		--比较横坐标
		if (((pos.x<=ppos[i].x and pos.x>=ppos[i+1].x ) or (pos.x>=ppos[i].x and pos.x<=ppos[i+1].x ))
			and math.abs(ppos[i+1].x-ppos[i].x)>200) or 
			(((pos.y<=ppos[i].y and pos.y>=ppos[i+1].y) or (pos.y>=ppos[i].y and pos.y<=ppos[i+1].y))
			and math.abs(ppos[i+1].y-ppos[i].y)>200)
			then
			return i+1
		end
	end
end

print("utility_functions inited")
